package com.nika.usercenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nika.usercenter.exception.BusinessException;
import com.nika.usercenter.mapper.TeamMapper;
import com.nika.usercenter.mapper.UserMapper;
import com.nika.usercenter.mapper.UserTeamMapper;
import com.nika.usercenter.model.domain.Team;
import com.nika.usercenter.model.domain.User;
import com.nika.usercenter.model.domain.UserTeam;
import com.nika.usercenter.model.dto.TeamQuery;
import com.nika.usercenter.model.enums.TeamStatusEnum;
import com.nika.usercenter.model.request.TeamJoinRequest;
import com.nika.usercenter.model.request.TeamQuitRequest;
import com.nika.usercenter.model.request.TeamUpdateRequest;
import com.nika.usercenter.model.vo.TeamVO;
import com.nika.usercenter.service.TeamService;
import com.nika.usercenter.service.UserService;
import com.nika.usercenter.service.UserTeamService;
import common.ErrorCode;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @author HT
 * @description 针对表【team(队伍)】的数据库操作Service实现
 * @createDate 2022-09-01 14:37:55
 */
@Service
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>
        implements TeamService {

    private final String TEAM_ID = "teamId";
    @Resource
    private UserTeamService userTeamService;

    @Resource
    private UserTeamMapper userTeamMapper;

    @Resource
    private UserService userService;

    @Resource
    private TeamMapper teamMapper;

    @Resource
    private UserMapper userMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    //开启事务 事务的定义:要么sql语句都执行成功，要么都失败，不存在存一个，另一个不存，或者一个不存，另一个存，这样会出现脏数据
    public long addTeam(Team team, User loginUser) {
        if (team == null || loginUser == null) {
            throw new BusinessException(ErrorCode.PARAMS_NULL_ERROR);
        }

        final long userId = loginUser.getId();

        Integer teamMaxNum = Optional.ofNullable(team.getMaxNum()).orElse(0);
        if (teamMaxNum < 1 || teamMaxNum > 20) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "人数不符合规定");
        }
        if (StringUtils.isBlank(team.getTeamName()) || team.getTeamName().length() > 20) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "标题超过20字，过长");
        }
        if (StringUtils.isNotBlank(team.getTeamDesc()) && team.getTeamDesc().length() > 512) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "描述超过512字，过长");
        }

        team.setTeamStatus(Optional.ofNullable(team.getTeamStatus()).orElse(0));

        TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByValue(team.getTeamStatus());

        if (statusEnum == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "传递的队伍状态枚举值不存在");
        }

        if (statusEnum.equals(TeamStatusEnum.SECRET)) {
            if (StringUtils.isEmpty(team.getTeamPassword())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "加密状态必须要有密码");
            }
            if (team.getTeamPassword().length() > 32) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "加密状态密码过长");
            }
        }

        if (new Date().after(team.getExpireTime())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "超时时间>当前时间");
        }
        //todo bug 如果用户疯狂点击，那么可能超过5个
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId);
        long teamCreatedNum = userTeamService.count(queryWrapper);
        if (teamCreatedNum >= 5) {
            throw new BusinessException(ErrorCode.NO_AUTH, "创建队伍数量大于5个,无权限");
        }
        team.setId(null);
        team.setUserId(userId);
        boolean teamSaveResult = save(team);
        Long teamId = team.getId();

        /**
         * 用于测试事务是否生效
         */
//        if(true){
//            throw new BusinessException(ErrorCode.NO_AUTH,"测试事务是否生效，如果生效，那么上面的save方法不会存team");
//        }

        if (!teamSaveResult || teamId == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "新增用户失败");
            //抛完异常，事务自动回滚
        }

        UserTeam userTeam = new UserTeam();
        userTeam.setTeamId(teamId);
        userTeam.setUserId(userId);
        userTeam.setJoinTime(new Date());
        boolean userTeamSaveResult = userTeamService.save(userTeam);

        if (!userTeamSaveResult) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "新增用户-队伍关系失败");
        }

        return teamId;
    }

    /**
     * teamvo里面是创建队伍的人
     *
     * @param teamQuery
     * @param loginUser
     * @return
     */
    @Override
    public List<TeamVO> query(TeamQuery teamQuery, User loginUser) {
        QueryWrapper<Team> teamQueryWrapper = new QueryWrapper<>();
        if (teamQuery != null) {
            Long id = teamQuery.getId();
            if (id != null) {
                teamQueryWrapper.eq("id", id);
            }
            String searchText = teamQuery.getSearchText();
            if (StringUtils.isNotBlank(searchText)) {
                teamQueryWrapper.and(teamQueryWrapper1 -> {
                    teamQueryWrapper1.like("teamName", searchText)
                            .or().like("teamDesc", searchText);
                });
            }

            String teamName = teamQuery.getTeamName();
            if (StringUtils.isNotBlank(teamName)) {
                teamQueryWrapper.like("teamName", teamName);
            }

            String teamDesc = teamQuery.getTeamDesc();
            if (StringUtils.isNotBlank(teamDesc)) {
                teamQueryWrapper.like("teamDesc", teamDesc);
            }

            Integer maxNum = teamQuery.getMaxNum();
            if (maxNum != null && maxNum > 0) {
                teamQueryWrapper.eq("maxNum", maxNum);
            }

            Long userId = teamQuery.getUserId();
            if (userId != null && userId > 0) {
                teamQueryWrapper.eq("userId", userId);
            }
            //如果说这个队伍状态 不是公共的 并且 你不是管理员，那么就抛没权限访问房间的异常
            Integer teamStatus = teamQuery.getTeamStatus();
            TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(teamStatus);

            if (teamStatusEnum == null) {
                teamStatusEnum = TeamStatusEnum.PUBLIC;
            }


            if (!userService.isAdmin(loginUser) && !teamStatusEnum.equals(TeamStatusEnum.PUBLIC)) {
                throw new BusinessException(ErrorCode.NO_AUTH, "没权限访问房间");
            }
            teamQueryWrapper.eq("teamStatus", teamStatusEnum.getValue());
        }

        //放在下面的原因是：当传入为空的时候，差的是全部，自动过滤废弃时间已经过了的数据
        //如果 传入得 时间为null 或者时间 早于废弃时间 就加入
        teamQueryWrapper.and(teamQueryWrapper1 -> teamQueryWrapper1.gt("expireTime", new Date()).or().isNull("expireTime"));

        ArrayList<TeamVO> teamVOS = new ArrayList<>();

        List<Team> teamList = list(teamQueryWrapper);
        for (Team team : teamList) {
            TeamVO teamVO = new TeamVO();
            BeanUtils.copyProperties(team, teamVO);
            Long userId = team.getUserId();
            if (userId != null && userId > 0) {
                User user = userService.getById(userId);
                if (user != null) {
                    teamVO.setUser(userService.getSafetyUser(user));
                }
            }
            teamVOS.add(teamVO);
        }
        return teamVOS;
    }

    @Override
    public boolean updateTeam(TeamUpdateRequest team, User loginUser) {
        if (team == null || team.getId() == null || team.getId() < 0 || loginUser == null) {
            throw new BusinessException(ErrorCode.PARAMS_NULL_ERROR);
        }
        Team team1 = teamMapper.selectById(team.getId());

        if (team1 == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "没有该队伍");
        }

        if (!userService.isAdmin(loginUser) && !team1.getUserId().equals(loginUser.getId())) {
            throw new BusinessException(ErrorCode.NO_AUTH, "无权限");
        }
        TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByValue(team.getTeamStatus());

        if (TeamStatusEnum.SECRET.equals(statusEnum) && StringUtils.isBlank(team.getTeamPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_NULL_ERROR);
        }
        Team teamUpdate = new Team();
        BeanUtils.copyProperties(team, teamUpdate);
        int result = teamMapper.updateById(teamUpdate);
        return result > 0;
    }

    @Override
    public boolean joinTeam(TeamJoinRequest teamJoinRequest, User loginUser) {
        QueryWrapper<UserTeam> queryWrapper;
        if (teamJoinRequest == null || loginUser == null) {
            throw new BusinessException(ErrorCode.PARAMS_NULL_ERROR);
        }
        Long teamJoinRequestId = teamJoinRequest.getId();
        if (teamJoinRequestId == null || teamJoinRequestId < 0) {
            throw new BusinessException(ErrorCode.PARAMS_NULL_ERROR);
        }

        long userId = loginUser.getId();
        Team team = teamMapper.selectById(teamJoinRequestId);
        if (team == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "加入的队伍不存在");
        }
        Date expireTime = team.getExpireTime();
        if (expireTime != null && expireTime.before(new Date())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "加入的队伍已经过时间");
        }
        Integer teamMaxNum = team.getMaxNum();
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(TEAM_ID, teamJoinRequestId);
        long teamHasJoinedNum = userTeamService.count(queryWrapper);
        if (teamHasJoinedNum >= teamMaxNum) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "加入的队伍人数已经满了");
        }
        TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(team.getTeamStatus());
        if (teamStatusEnum.equals(TeamStatusEnum.SECRET)) {
            if (StringUtils.isBlank(teamJoinRequest.getTeamPassword())) {
                throw new BusinessException(ErrorCode.PARAMS_NULL_ERROR, "加入私密房间需要密码");
            }
            if (!StringUtils.equals(teamJoinRequest.getTeamPassword(), team.getTeamPassword())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "加入私密房间密码不正确");
            }
        }
        if (teamStatusEnum.equals(TeamStatusEnum.PRIVATE)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "加入私有房间密码不正确");
        }
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId);
        queryWrapper.eq(TEAM_ID, teamJoinRequestId);
        long userHasJoinTeam = userTeamService.count(queryWrapper);
        if (userHasJoinTeam > 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "您不能重复加入已经加入的队伍");
        }
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId);
        long count = userTeamService.count(queryWrapper);
        if (count >= 5) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户最多加入5个队伍");
        }
        UserTeam userTeam = new UserTeam();
        userTeam.setTeamId(teamJoinRequestId);
        userTeam.setUserId(userId);
        userTeam.setJoinTime(new Date());
        return userTeamService.save(userTeam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean quit(TeamQuitRequest teamQuitRequest, User loginUser) {
        if (teamQuitRequest == null || teamQuitRequest.getId() ==null ||teamQuitRequest.getId()<=0 ) {
            throw new BusinessException(ErrorCode.PARAMS_NULL_ERROR);
        }
        final long userId = loginUser.getId();
        final long teamId = teamQuitRequest.getId();
        Team team = getById(teamId);
        if (team == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍不存在");
        }
        QueryWrapper<UserTeam> queryWrapper;

        //判断是否登录用户已经加入队伍
        UserTeam userTeamCheckIsInTeam = new UserTeam();
        userTeamCheckIsInTeam.setTeamId(teamId);
        userTeamCheckIsInTeam.setUserId(userId);
        queryWrapper = new QueryWrapper<>(userTeamCheckIsInTeam);
        long count = userTeamService.count(queryWrapper);
        if(count == 0){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"登录用户没有加入队伍");
        }
        //判断队伍成员数量
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(TEAM_ID, teamId);
        long countMember = userTeamService.count(queryWrapper);
        //说明只有一个人
        if (countMember < 2) {
            boolean teamResult = this.removeById(teamId);
            queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(TEAM_ID,teamId);
            boolean userTeamResult = userTeamService.remove(queryWrapper);
            return teamResult && userTeamResult;
        }
        //说明现在登录用户是队长，队伍至少有两个人
        if (userId == team.getUserId()) {
            queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(TEAM_ID,teamId);
            //根据userTeam Id是增序，可以看出第一个是队长，第二个是顺位的队员
            queryWrapper.last("order by id asc limit 2");
            List<UserTeam> userTeamList = userTeamService.list(queryWrapper);
            if(CollectionUtils.isEmpty(userTeamList) || userTeamList.size() < 2){
                throw new BusinessException(ErrorCode.SYSTEM_ERROR);
            }
            UserTeam userTeam = userTeamList.get(1);
            Long nextTeamLeaderId = userTeam.getUserId();
            Team teamUpdate = new Team();
            teamUpdate.setId(teamId);
            teamUpdate.setUserId(nextTeamLeaderId);
            boolean updateResult = this.updateById(teamUpdate);
            if(!updateResult){
                throw new BusinessException(ErrorCode.SYSTEM_ERROR,"更新队长失败");
            }
        }
        queryWrapper =new QueryWrapper<>();
        queryWrapper.eq("userId",userId);
        queryWrapper.eq(TEAM_ID,teamId);
        return userTeamService.remove(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public boolean delTeam(Long id, User loginUser) {
        if(id == null || id<= 0){
            throw new BusinessException(ErrorCode.PARAMS_NULL_ERROR);
        }
        Team team = this.getById(id);
        if(team == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍不存在");
        }
        if(team.getUserId() != loginUser.getId()){
            throw new BusinessException(ErrorCode.FORBIDDEN);
        }
        boolean removeTeam = this.removeById(id);
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("teamId",id);
        boolean removeUserTeam = userTeamService.remove(queryWrapper);
        return removeTeam && removeUserTeam;
    }


}




